/*
 * complex.h
 *
 *  Created on: Oct 21, 2011
 *      Author: ivanovak
 *
 *      rational numbers class (don't know why it's called complex =P)
 */

#ifndef COMPLEX_H_
#define COMPLEX_H_

#include <iostream>

class Rational {
private:
	int p;
	int q;
public:
	static void flip(Rational&);
	int GCD(int, int);
	void simplify();
	void printIt();
	Rational(int, int);
	//Rational(const Rational&);	// we have this constructor by default

	Rational operator+(const Rational&) const; // +
	Rational operator-(const Rational&) const; // +
	Rational operator/(const Rational&) const; // +
	Rational operator*(const Rational&) const; // +

	Rational & operator+=(const Rational&); //+
	Rational & operator*=(const Rational&); //+
	Rational & operator/=(const Rational&); //+
	Rational & operator-=(const Rational&); //+

	Rational operator-() const; // +

	friend bool operator<(const Rational&, const Rational&);
	friend bool operator>(const Rational&, const Rational&);

	operator double() const;

};

//Rational::Rational(const Rational &rat) {
//	p = rat.p;
//	q = rat.q;
//}

void Rational::flip(Rational &rat) {
	int t = rat.p;
	rat.p = rat.q;
	rat.q = t;
}
void Rational::simplify(){
	int gcd = GCD(p, q);
	p/=gcd;
	q/=gcd;
}

Rational::operator double() const {
	return (double)this->p/(double)this->q;
}

Rational::Rational(int a , int b = 1){
	p = a;
	q = b;
	simplify();
}

void Rational::printIt() {
	std::cout << p << "/" << q << std::endl;
}

Rational Rational::operator-() const {
	Rational a(-p, q);
	return a;
}

Rational Rational::operator+(const Rational& rat) const{
	Rational a(rat);
	a+=*this;
	a.simplify();
	return a;
}

Rational Rational::operator-(const Rational& rat) const{
	Rational a(rat);
	a+=-(*this);
	a.simplify();
	return a;
}

Rational Rational::operator*(const Rational& rat) const{
	Rational a(rat);
	a*=*this;
	a.simplify();
	return a;
}

Rational Rational::operator/(const Rational& rat) const{
	Rational a(rat);
	flip(a);
	a.simplify();
	return a*(*this);
}

Rational & Rational::operator+=(const Rational& rat){
	p = rat.p*q+p*rat.q;
	q = rat.q*q;
	return *this;
}


Rational & Rational::operator-=(const Rational& rat){
	return (*this+=(-rat));
}

Rational & Rational::operator*=(const Rational& rat){
	this->p = this->p*rat.p;
	this->q = this->q*rat.q;
	return *this;
}

Rational & Rational::operator/=(const Rational& rat){
	this->p = this->p*rat.q;
	this->q = this->q*rat.p;
	return *this;
}

bool operator<(const Rational& a, const Rational& b) {
	return (a.p*b.q < a.q*b.p);
}
bool operator>(const Rational& a, const Rational& b) {
	return (a.p*b.q > a.q*b.p);
}
bool operator!=(const Rational& a, const Rational& b) {
	return !(a==b);
}

bool operator==(const Rational& a, const Rational& b) {
	return !((a < b) || (a > b));
}

bool operator>=(const Rational& a, const Rational& b) {
	return !(a < b);
}

bool operator<=(const Rational& a, const Rational& b) {
	return !(a > b);
}

int Rational::GCD(int a, int b){
	if(b == 0) return a;
	return GCD(b, a%b);
}

#endif /* COMPLEX_H_ */
